/*
 * Copyright Iain Sproat, 2008
 * 
 *
 */
using System;
using System.Collections.Generic;

namespace FreeBase.Fluent
{
	public class FBQuery
	{
		#region Private variables
		IList<FBCriteria> _criteria = new List<FBCriteria>();
		IList<FBPlaceholder> _placeholders = new List<FBPlaceholder>();
		IList<FBDirective> _directives = new List<FBDirective>();
		IList<FBInnerQuery> _innerQueries = new List<FBInnerQuery>();
		bool _isArray = true;
		#endregion
		
		#region Directly Accessible Components of the Query
		internal IList<FBCriteria> Criteria
		{
			get{ return this._criteria; }
		}
		
		internal IList<FBPlaceholder> Placeholders
		{
			get{ return this._placeholders; }
		}
		
		internal IList<FBDirective> Directives
		{
			get{ return this._directives; }
		}
		
		internal IList<FBInnerQuery> InnerQueries
		{
			get{ return this._innerQueries; }
		}
		
		//FIXME is this needed?/should it be allowed?
		internal void AddCriteria( FBCriteria criteria )
		{
			if( criteria == null )
				throw new ArgumentNullException( "criteria" );
			this._criteria.Add( criteria );
		}
		#endregion
		
		#region Fluent Extensions
		public FBCriteria Where()
		{
			return this.Where( string.Empty );
		}
		
		public FBCriteria Where( string propertyName ){
			FBCriteria w = new FBCriteria( this );
			w.JoinType = JoinType.AND;
			if( !string.IsNullOrEmpty ( propertyName ) )
				w.PropertyName = propertyName;
			return w;
		}
		
		public FBInnerQuery Expect
		{
			get{
				FBInnerQuery w = new FBInnerQuery( this );
				this._innerQueries.Add( w );
				return w;
			}
		}
		
		public FBPlaceholder Show
		{
			get{
				FBPlaceholder p = new FBPlaceholder( this );
				this._placeholders.Add( p );
				return p;
			}
		}
		
		public FBDirective Create
		{
			get{
				FBDirective d = new FBDirective( DirectiveType.Create, this );
				this._directives.Add( d );
				return d;
			}
		}
		
		public FBDirective LimitNumberOfResults
		{
			get{
				FBDirective d = new FBDirective( DirectiveType.Limit, this );
				this._directives.Add( d );
				return d;
			}
		}
		
		public FBDirective Sort
		{
			get{
				FBDirective d = new FBDirective( DirectiveType.Sort, this );
				this._directives.Add( d );
				return d;
			}
		}
		
		public FBDirective ReverseSort
		{
			get{
				FBDirective d = new FBDirective( DirectiveType.ReverseSort, this );
				this._directives.Add( d );
				return d;
			}
		}
		
		public FBDirective Optional
		{
			get{
				FBDirective d = new FBDirective( DirectiveType.Optional, this );
				this._directives.Add( d );
				return d;
			}
		}
		
		public FBDirective Return
		{
			get{
				FBDirective d = new FBDirective( DirectiveType.Return, this );
				this._directives.Add( d );
				return d;
			}
		}
		
		public FBQuery Count
		{
			get{
				FBDirective d = new FBDirective( DirectiveType.Count, this );
				this._directives.Add( d );
				return this;
			}
		}
		
		public FBDirective EstimateCount
		{
			get{
				FBDirective d = new FBDirective( DirectiveType.EstimateCount, this );
				this._directives.Add( d );
				return d;
			}
		}
		internal bool IsArray
		{
			get{ return this._isArray; }
			set{ this._isArray = value; }
		}
		#endregion
	}
}
